這篇是我建一個部落格系統的心得,目標是能讓所有使用者能夠像階層式的管理自己的部落格文章,因為是學習用途,我會加上一些我想學的應用在系統裡面,主要語言會用到go與mysql,請多多指教。
先把想要完成的服務規劃好,方便動工,以下是一開始的規劃。
由此定義以下網址,之後搭配CRUD操作寫REST API
這系列的文章會用到docker,主要的程式碼語言是go,雖然有docker就夠了,不過還是建議連go都安裝好
先建立以下工作環境
.
├── app
│ ├── main.go
│ └── config
└── database
進入app後輸入
go mod init app
使用go mod的好處是會自動幫你拉import的第三方package,很方便。
如果不想把私密的檔案一起commmit,可以建一個.gitignore檔案來新增忽略名單
touch .gitignore
在裡面寫入
# 忽略設定檔
/config
# 忽略自己
.gitignore
這樣之後正常的git操作就會忽略這些檔案了
應該沒有人會想把所有程序配置與公共參數全部都寫死在source code裡面吧(例如database的密碼)?
常見的作法是把參數寫在設定擋上,再寫一個配置pkg,統一讀取與管理。
設定檔格式有很多選擇,簡單介紹一下
這邊使用yaml來編寫。
在config下建立app資料夾,接著建立app.yaml,寫入
---
servers:
main:
host: local.com # 自訂網址
port: 80 # app綁定的port
RunMode: debug # gin run mode
ReadTimeout: 60s # http.server.ReadTimeout
WriteTimeout: 60s # http.server.WriteTimeout
...
先寫這些,之後可以視情況新增其他資料,有需要甚至可以將整個server struct都在yaml設定好。
我們只需要讀取,並不需要複雜的操作,所以yaml parser使用gopkg.in/yaml.v3,如果想要更複雜點可以試試github.com/goccy/go-yaml
在app中建立setting package在setting下創建setting.go,寫入
package setting
import (
"gopkg.in/yaml.v3"
"io/ioutil"
)
type ServerStruct struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
RunMode string `yaml:"RunMode,omitempty"`
ReadTimeout time.Duration `yaml:"ReadTimeout,omitempty"`
WriteTimeout time.Duration `yaml:"WriteTimeout,omitempty"`
}
type ConfigStruct struct {
Servers map[string]*ServerStruct
}
解釋
yaml:"WriteTimeout,omitempty"
對應yaml的WriteTimeout key,omitempty代表yaml檔中這field可以省略不寫上面只是型態而已,接著
var (
WorkPath = "./config/app/"
Config *ConfigStruct
Servers map[string]*ServerStruct
)
func init() {
// read file
config, err := ioutil.ReadFile(WorkPath + "app.yaml")
if err != nil {
panic(err)
}
// binding
var c ConfigStruct
err = yaml.Unmarshal(config, &c)
if err != nil {
panic(err)
}
Config = &c
Servers = Config.Servers
}
解釋:
var c ConfigStruct
很重要,如果沒有給值,go初始化的物件都會有zero value,指標Config *ConfigStruct
的zero value為nil,直接用nil去bind是會跳錯誤的,而var c ConfigStruct
不是指標,而是一個型態zero value為**{map[]}**,可以自己用Println看看先帶過設定檔,之後依照需求慢慢加入更多參數
現在的目錄長這樣
.
├── app
│ ├── config
│ │ └── app
│ │ └── app.yaml
│ ├── go.mod
│ ├── main.go
│ └── setting
│ └── setting.go
└── database